home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / termv4.6 / extras / source / term-source.lha / Identify.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-18  |  18.7 KB  |  1,005 lines

  1. /*
  2. **    Identify.c
  3. **
  4. **    Heuristic file type identification routines (big words!).
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #ifndef _GLOBAL_H
  11. #include "Global.h"
  12. #endif
  13.  
  14.     /* The file types we know. */
  15.  
  16. enum    {    TYPE_DIR,TYPE_FILE,
  17.         TYPE_ICON,
  18.         TYPE_TEXT,
  19.         TYPE_C,TYPE_H,
  20.         TYPE_ASM,TYPE_I,
  21.         TYPE_MOD,
  22.         TYPE_REXX,
  23.         TYPE_BASIC,
  24.         TYPE_AMIGAGUIDE,
  25.         TYPE_TEX,TYPE_METAFONT,TYPE_GF,TYPE_TEXFONT,TYPE_TEXDVI,TYPE_FLIB,
  26.         TYPE_OLDMANX,TYPE_NEWMANX,TYPE_OLDMANXLIB,TYPE_NEWMANXLIB,
  27.         TYPE_OBJECT,TYPE_LIB,
  28.         TYPE_EXECUTABLE,
  29.         TYPE_LIBRARY,TYPE_DEVICE,TYPE_FILESYS,TYPE_HANDLER,
  30.         TYPE_GIF,TYPE_DEGAS,TYPE_MACPAINT,TYPE_SUPERPAINT,TYPE_PICT,TYPE_SUNRASTER,TYPE_POSTSCRIPT,TYPE_PCX,TYPE_TIFF,TYPE_BMP,TYPE_JFIF,TYPE_ILBM,
  31.         TYPE_ANIM,TYPE_8SVX,TYPE_SMUS,TYPE_FTXT,TYPE_PREFS,TYPE_TERM,TYPE_AMIGAVISION,TYPE_IFF,
  32.         TYPE_IMPLODER,TYPE_POWERPACKER,TYPE_LHPAK,TYPE_LHASFX,
  33.         TYPE_ARC,TYPE_ARJ,TYPE_COMPRESSED,TYPE_CPIO,TYPE_UUENCODED,TYPE_FREEZE,TYPE_MACCOMPRESS,TYPE_COMPACT,TYPE_DIAMOND,TYPE_LHARC,TYPE_LHA,TYPE_ZOO,TYPE_ZIP,TYPE_STUFFIT,TYPE_PACKIT,TYPE_DMS,TYPE_WARP,TYPE_ZOOM,
  34.         TYPE_SPARCOBJECT,TYPE_SPARCEXECUTABLE,
  35.         TYPE_MSDOSEXECUTABLE,
  36.         TYPE_ATARIEXECUTABLE,
  37.         TYPE_MACEXECUTABLE,
  38.         TYPE_CDAF,TYPE_XPK,
  39.         TYPE_PNG,TYPE_LZX,
  40.  
  41.         TYPE_COUNT
  42.     };
  43.  
  44.     // Locale string IDs for the file types
  45.  
  46. UWORD TypeID[TYPE_COUNT] =
  47. {
  48.     MSG_IDENTIFY_FILETYPE_0,
  49.     MSG_IDENTIFY_FILETYPE_1,
  50.     MSG_IDENTIFY_FILETYPE_2,
  51.     MSG_IDENTIFY_FILETYPE_3,
  52.     MSG_IDENTIFY_FILETYPE_4,
  53.     MSG_IDENTIFY_FILETYPE_5,
  54.     MSG_IDENTIFY_FILETYPE_6,
  55.     MSG_IDENTIFY_FILETYPE_7,
  56.     MSG_IDENTIFY_FILETYPE_8,
  57.     MSG_IDENTIFY_FILETYPE_9,
  58.     MSG_IDENTIFY_FILETYPE_10,
  59.     MSG_IDENTIFY_FILETYPE_11,
  60.     MSG_IDENTIFY_FILETYPE_12,
  61.     MSG_IDENTIFY_FILETYPE_13,
  62.     MSG_IDENTIFY_FILETYPE_14,
  63.     MSG_IDENTIFY_FILETYPE_15,
  64.     MSG_IDENTIFY_FILETYPE_16,
  65.     MSG_IDENTIFY_FILETYPE_17,
  66.     MSG_IDENTIFY_FILETYPE_18,
  67.     MSG_IDENTIFY_FILETYPE_19,
  68.     MSG_IDENTIFY_FILETYPE_20,
  69.     MSG_IDENTIFY_FILETYPE_21,
  70.     MSG_IDENTIFY_FILETYPE_22,
  71.     MSG_IDENTIFY_FILETYPE_23,
  72.     MSG_IDENTIFY_FILETYPE_24,
  73.     MSG_IDENTIFY_FILETYPE_25,
  74.     MSG_IDENTIFY_FILETYPE_26,
  75.     MSG_IDENTIFY_FILETYPE_27,
  76.     MSG_IDENTIFY_FILETYPE_28,
  77.     MSG_IDENTIFY_FILETYPE_29,
  78.     MSG_IDENTIFY_FILETYPE_30,
  79.     MSG_IDENTIFY_FILETYPE_31,
  80.     MSG_IDENTIFY_FILETYPE_32,
  81.     MSG_IDENTIFY_FILETYPE_33,
  82.     MSG_IDENTIFY_FILETYPE_34,
  83.     MSG_IDENTIFY_FILETYPE_35,
  84.     MSG_IDENTIFY_FILETYPE_36,
  85.     MSG_IDENTIFY_FILETYPE_37,
  86.     MSG_IDENTIFY_FILETYPE_38,
  87.     MSG_IDENTIFY_FILETYPE_39,
  88.     MSG_IDENTIFY_FILETYPE_40,
  89.     MSG_IDENTIFY_FILETYPE_41,
  90.     MSG_IDENTIFY_FILETYPE_42,
  91.     MSG_IDENTIFY_FILETYPE_43,
  92.     MSG_IDENTIFY_FILETYPE_44,
  93.     MSG_IDENTIFY_FILETYPE_45,
  94.     MSG_IDENTIFY_FILETYPE_46,
  95.     MSG_IDENTIFY_FILETYPE_47,
  96.     MSG_IDENTIFY_FILETYPE_48,
  97.     MSG_IDENTIFY_FILETYPE_49,
  98.     MSG_IDENTIFY_FILETYPE_50,
  99.     MSG_IDENTIFY_FILETYPE_51,
  100.     MSG_IDENTIFY_FILETYPE_52,
  101.     MSG_IDENTIFY_FILETYPE_53,
  102.     MSG_IDENTIFY_FILETYPE_54,
  103.     MSG_IDENTIFY_FILETYPE_55,
  104.     MSG_IDENTIFY_FILETYPE_56,
  105.     MSG_IDENTIFY_FILETYPE_57,
  106.     MSG_IDENTIFY_FILETYPE_58,
  107.     MSG_IDENTIFY_FILETYPE_59,
  108.     MSG_IDENTIFY_FILETYPE_60,
  109.     MSG_IDENTIFY_FILETYPE_61,
  110.     MSG_IDENTIFY_FILETYPE_62,
  111.     MSG_IDENTIFY_FILETYPE_63,
  112.     MSG_IDENTIFY_FILETYPE_64,
  113.     MSG_IDENTIFY_FILETYPE_65,
  114.     MSG_IDENTIFY_FILETYPE_66,
  115.     MSG_IDENTIFY_FILETYPE_67,
  116.     MSG_IDENTIFY_FILETYPE_68,
  117.     MSG_IDENTIFY_FILETYPE_69,
  118.     MSG_IDENTIFY_FILETYPE_70,
  119.     MSG_IDENTIFY_FILETYPE_71,
  120.     MSG_IDENTIFY_FILETYPE_72,
  121.     MSG_IDENTIFY_FILETYPE_73,
  122.     MSG_IDENTIFY_CDAF,
  123.     MSG_IDENTIFY_XPK,
  124.     MSG_IDENTIFY_FILETYPE_74,
  125.     MSG_IDENTIFY_FILETYPE_75
  126. };
  127.  
  128.     /* File type/class mappings. */
  129.  
  130. STATIC WORD FileTypes[TYPE_COUNT] =
  131. {
  132.     FILETYPE_DIR,
  133.     FILETYPE_FILE,
  134.     FILETYPE_NONE,
  135.     FILETYPE_TEXT,
  136.     FILETYPE_TEXT,
  137.     FILETYPE_TEXT,
  138.     FILETYPE_TEXT,
  139.     FILETYPE_TEXT,
  140.     FILETYPE_TEXT,
  141.     FILETYPE_TEXT,
  142.     FILETYPE_TEXT,
  143.     FILETYPE_TEXT,
  144.     FILETYPE_TEXT,
  145.     FILETYPE_FILE,
  146.     FILETYPE_FILE,
  147.     FILETYPE_FILE,
  148.     FILETYPE_FILE,
  149.     FILETYPE_FILE,
  150.     FILETYPE_FILE,
  151.     FILETYPE_FILE,
  152.     FILETYPE_FILE,
  153.     FILETYPE_FILE,
  154.     FILETYPE_FILE,
  155.     FILETYPE_FILE,
  156.     FILETYPE_PROGRAM,
  157.     FILETYPE_FILE,
  158.     FILETYPE_FILE,
  159.     FILETYPE_FILE,
  160.     FILETYPE_FILE,
  161.     FILETYPE_PICTURE,
  162.     FILETYPE_PICTURE,
  163.     FILETYPE_PICTURE,
  164.     FILETYPE_PICTURE,
  165.     FILETYPE_PICTURE,
  166.     FILETYPE_PICTURE,
  167.     FILETYPE_PICTURE,
  168.     FILETYPE_PICTURE,
  169.     FILETYPE_PICTURE,
  170.     FILETYPE_PICTURE,
  171.     FILETYPE_PICTURE,
  172.     FILETYPE_PICTURE,
  173.     FILETYPE_PICTURE,
  174.     FILETYPE_SOUND,
  175.     FILETYPE_SOUND,
  176.     FILETYPE_TEXT,
  177.     FILETYPE_PREFS,
  178.     FILETYPE_PREFS,
  179.     FILETYPE_FILE,
  180.     FILETYPE_FILE,
  181.     FILETYPE_ARCHIVE,
  182.     FILETYPE_ARCHIVE,
  183.     FILETYPE_ARCHIVE,
  184.     FILETYPE_ARCHIVE,
  185.     FILETYPE_ARCHIVE,
  186.     FILETYPE_ARCHIVE,
  187.     FILETYPE_ARCHIVE,
  188.     FILETYPE_ARCHIVE,
  189.     FILETYPE_TEXT,
  190.     FILETYPE_ARCHIVE,
  191.     FILETYPE_ARCHIVE,
  192.     FILETYPE_ARCHIVE,
  193.     FILETYPE_ARCHIVE,
  194.     FILETYPE_ARCHIVE,
  195.     FILETYPE_ARCHIVE,
  196.     FILETYPE_ARCHIVE,
  197.     FILETYPE_ARCHIVE,
  198.     FILETYPE_ARCHIVE,
  199.     FILETYPE_ARCHIVE,
  200.     FILETYPE_ARCHIVE,
  201.     FILETYPE_ARCHIVE,
  202.     FILETYPE_ARCHIVE,
  203.     FILETYPE_PROGRAM,
  204.     FILETYPE_PROGRAM,
  205.     FILETYPE_PROGRAM,
  206.     FILETYPE_PROGRAM,
  207.     FILETYPE_PROGRAM,
  208.     FILETYPE_ARCHIVE,
  209.     FILETYPE_ARCHIVE,
  210.     FILETYPE_PICTURE,
  211.     FILETYPE_ARCHIVE
  212. };
  213.  
  214.     /* File class icon names. */
  215.  
  216. STATIC STRPTR ClassIconNames[FILETYPE_COUNT] =
  217. {
  218.     NULL,
  219.     "ENV:sys/def_drawer",
  220.     "ENV:sys/def_project",
  221.     "ENV:sys/def_text",
  222.     "ENV:sys/def_sound",
  223.     "ENV:sys/def_picture",
  224.     "ENV:sys/def_pref",
  225.     "ENV:sys/def_archive",
  226.     "ENV:sys/def_tool",
  227. };
  228.  
  229.     /* A structure containing both a file name suffix and the
  230.      * appropriate file type.
  231.      */
  232.  
  233. struct Suffix
  234. {
  235.     UBYTE    *Name;
  236.     UBYTE     Type;
  237. };
  238.  
  239.     /* A table of valid ASCII characters (7 bits). */
  240.  
  241. STATIC BYTE ID_ValidTab[256] =
  242. {
  243.     0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,
  244.     0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,
  245.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  246.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  247.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  248.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  249.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  250.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  251.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  252.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  253.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  254.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  255.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  256.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  257.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  258.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  259. };
  260.  
  261.     /* A table of clearly invalid ASCII characters (8 bits). */
  262.  
  263. STATIC BYTE ID_InvalidTab[256] =
  264. {
  265.     1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,
  266.     1,0,1,0,1,1,1,1,1,1,1,0,1,1,1,1,
  267.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  268.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  269.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  270.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  271.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  272.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  273.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  274.     1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,
  275.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  276.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  277.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  278.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  279.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  280.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  281. };
  282.  
  283.     /* Some file name suffixes for text files and the appropriate
  284.      * file types.
  285.      */
  286.  
  287. STATIC struct Suffix TextSuffix[] =
  288. {
  289.     ".C",        TYPE_C,
  290.     ".CPP",        TYPE_C,
  291.     ".CXX",        TYPE_C,
  292.     ".C++",        TYPE_C,
  293.     ".CC",        TYPE_C,
  294.     ".H",        TYPE_H,
  295.     ".ASM",        TYPE_ASM,
  296.     ".A",        TYPE_ASM,
  297.     ".S",        TYPE_ASM,
  298.     ".I",        TYPE_I,
  299.     ".BAS",        TYPE_BASIC,
  300.     ".GFA",        TYPE_BASIC,
  301.     ".REXX",    TYPE_REXX,
  302.     ".CED",        TYPE_REXX,
  303.     ".TTX",        TYPE_REXX,
  304.     ".VLT",        TYPE_REXX,
  305.     ".CPR",        TYPE_REXX,
  306.     ".TxEd",    TYPE_REXX,
  307.     ".ADPro",    TYPE_REXX,
  308.     ".TEX",        TYPE_TEX,
  309.     ".STY",        TYPE_TEX,
  310.     ".MF",        TYPE_METAFONT,
  311.     ".MOD",        TYPE_MOD,
  312.     ".DEF",        TYPE_MOD,
  313.     ".PS",        TYPE_POSTSCRIPT,
  314.     ".GUIDE",    TYPE_AMIGAGUIDE,
  315.     ".UUE",        TYPE_UUENCODED
  316. };
  317.  
  318.     /* Some more file name suffixes for executable files and the
  319.      * appropriate file types.
  320.      */
  321.  
  322. STATIC struct Suffix ExecutableSuffix[] =
  323. {
  324.     ".device",    TYPE_DEVICE,
  325.     ".library",    TYPE_LIBRARY,
  326.     "FileSystem",    TYPE_FILESYS,
  327.     "Handler",    TYPE_HANDLER
  328. };
  329.  
  330.     /* Miscellaneous magic cookies. */
  331.  
  332. STATIC STRPTR MagicCookies[] =
  333. {
  334.     "P1",
  335.     "P2",
  336.     "P3",
  337.     "P4",
  338.     "P5",
  339.     "P6",
  340.     "begin",
  341.     "xbtoa"
  342. };
  343.  
  344.     /* LongCompare(UBYTE *Buffer,ULONG Value):
  345.      *
  346.      *    Compare space in memory with a longword value.
  347.      */
  348.  
  349. STATIC BOOL
  350. LongCompare(UBYTE *Buffer,ULONG Value)
  351. {
  352.     UBYTE *OtherBuffer = (UBYTE *)&Value,i;
  353.  
  354.     for(i = 0 ; i < 4 ; i++)
  355.     {
  356.         if(OtherBuffer[i] != Buffer[i])
  357.             return(FALSE);
  358.     }
  359.  
  360.     return(TRUE);
  361. }
  362.  
  363.     /* GetFileType(STRPTR Name,BOOL AttachComment):
  364.      *
  365.      *    Simple routine to identify a file type by looking at
  366.      *    its first 400 bytes. If successful a comment is
  367.      *    attached to the file describing the file type.
  368.      */
  369.  
  370. LONG
  371. GetFileType(STRPTR Name,BOOL AttachComment)
  372. {
  373.     ULONG    *Buffer;
  374.     LONG     Type        = TYPE_FILE;
  375.     STRPTR     TypeName    = NULL;
  376.     LONG     i,
  377.          Len = strlen(Name);
  378.     UBYTE     IFFType[5];
  379.  
  380.         /* Allocate a buffer for the first 410 bytes of the
  381.          * file.
  382.          */
  383.  
  384.     if(Buffer = (ULONG *)AllocVecPooled(410,MEMF_ANY | MEMF_CLEAR))
  385.     {
  386.         BPTR File,Size;
  387.  
  388.             /* Open the file. */
  389.  
  390.         if(File = Open(Name,MODE_OLDFILE))
  391.         {
  392.                 /* Read the first 410 bytes. */
  393.  
  394.             if((Size = Read(File,Buffer,410)) >= sizeof(ULONG))
  395.             {
  396.                 UBYTE    *CharBuffer = (UBYTE *)Buffer;
  397.                 LONG     Count = 0;
  398.  
  399.                     /* See if it's an ASCII file. */
  400.  
  401.                 for(i = 0 ; i < Size ; i++)
  402.                 {
  403.                     if(ID_ValidTab[CharBuffer[i]])
  404.                         Count++;
  405.                     else
  406.                     {
  407.                         if(ID_InvalidTab[CharBuffer[i]])
  408.                         {
  409.                             Count = 0;
  410.  
  411.                             break;
  412.                         }
  413.                     }
  414.                 }
  415.  
  416.                     /* If more than 75% of the
  417.                      * characters in the first
  418.                      * 400 bytes are legal
  419.                      * ASCII characters this
  420.                      * file is supposed to be
  421.                      * a text file.
  422.                      */
  423.  
  424.                 if(Count > 3 * (Size / 4))
  425.                     Type = TYPE_TEXT;
  426.  
  427.                     /* Examine the first longword. */
  428.  
  429.                 if(Type == TYPE_FILE)
  430.                 {
  431.                     switch(Buffer[0])
  432.                     {
  433.                         case 0x4C5A5800:
  434.  
  435.                             Type = TYPE_LZX;
  436.                             break;
  437.  
  438.                         case 0x58504B46:
  439.  
  440.                             Type = TYPE_XPK;
  441.                             break;
  442.  
  443.                         case 0x000003E7:
  444.  
  445.                             Type = TYPE_OBJECT;
  446.                             break;
  447.  
  448.                         case 0x000003F3:
  449.  
  450.                             if(Buffer[10] == 'LSFX')
  451.                                 Type = TYPE_LHPAK;
  452.                             else
  453.                             {
  454.                                 if(Buffer[11] == 'SFX!')
  455.                                     Type = TYPE_LHASFX;
  456.                                 else
  457.                                     Type = TYPE_EXECUTABLE;
  458.                             }
  459.  
  460.                             break;
  461.  
  462.                         case 0x000003FA:
  463.  
  464.                             Type = TYPE_LIB;
  465.                             break;
  466.  
  467.                         case 0xF7593647:
  468.  
  469.                             Type = TYPE_TEXFONT;
  470.                             break;
  471.  
  472.                         case 0xF7020183:
  473.  
  474.                             Type = TYPE_TEXDVI;
  475.                             break;
  476.  
  477.                         case 0xF7832020:
  478.  
  479.                             Type = TYPE_GF;
  480.                             break;
  481.  
  482.                         case 0x504B0304:
  483.  
  484.                             Type = TYPE_ZIP;
  485.                             break;
  486.  
  487.                         case 0x01030107:
  488.  
  489.                             Type = TYPE_SPARCOBJECT;
  490.                             break;
  491.  
  492.                         case 0x8103010B:
  493.  
  494.                             Type = TYPE_SPARCEXECUTABLE;
  495.                             break;
  496.  
  497.                         case 0x59A66A95:
  498.  
  499.                             Type = TYPE_SUNRASTER;
  500.                             break;
  501.  
  502.                         case 0x1F9D902A:
  503.  
  504.                             Type = TYPE_COMPRESSED;
  505.                             break;
  506.  
  507.                         case 0x30373037:
  508.  
  509.                             Type = TYPE_CPIO;
  510.                             break;
  511.  
  512.                         case 'FLIB':
  513.  
  514.                             Type = TYPE_FLIB;
  515.                             break;
  516.  
  517.                         case '\211PNG':
  518.  
  519.                             Type = TYPE_PNG;
  520.                             break;
  521.  
  522.                         case 'FORM':
  523.  
  524.                             switch(Buffer[2])
  525.                             {
  526.                                 case 'ILBM':
  527.  
  528.                                     Type = TYPE_ILBM;
  529.                                     break;
  530.  
  531.                                 case 'ANIM':
  532.  
  533.                                     Type = TYPE_ANIM;
  534.                                     break;
  535.  
  536.                                 case '8SVX':
  537.  
  538.                                     Type = TYPE_8SVX;
  539.                                     break;
  540.  
  541.                                 case 'SMUS':
  542.  
  543.                                     Type = TYPE_SMUS;
  544.                                     break;
  545.  
  546.                                 case 'FTXT':
  547.  
  548.                                     Type = TYPE_FTXT;
  549.                                     break;
  550.  
  551.                                 case 'PREF':
  552.  
  553.                                     Type = TYPE_PREFS;
  554.                                     break;
  555.  
  556.                                 case 'TERM':
  557.  
  558.                                     Type = TYPE_TERM;
  559.                                     break;
  560.  
  561.                                 case 'AVCF':
  562.  
  563.                                     Type = TYPE_AMIGAVISION;
  564.                                     break;
  565.  
  566.                                 case 'CDAF':
  567.  
  568.                                     Type = TYPE_CDAF;
  569.                                     break;
  570.  
  571.                                 default:
  572.  
  573.                                     Type = TYPE_IFF;
  574.  
  575.                                     CopyMem(&Buffer[2],IFFType,4);
  576.  
  577.                                     IFFType[4] = 0;
  578.  
  579.                                     break;
  580.                             }
  581.  
  582.                             break;
  583.  
  584.                         case 'IMP!':
  585.  
  586.                             Type = TYPE_IMPLODER;
  587.                             break;
  588.  
  589.                         case 'PP20':
  590.  
  591.                             Type = TYPE_POWERPACKER;
  592.                             break;
  593.  
  594.                         case 'DMS!':
  595.  
  596.                             Type = TYPE_DMS;
  597.                             break;
  598.  
  599.                         case 'Warp':
  600.  
  601.                             Type = TYPE_WARP;
  602.                             break;
  603.  
  604.                         case 'ZOM5':
  605.                         case 'ZOOM':
  606.  
  607.                             Type = TYPE_ZOOM;
  608.                             break;
  609.  
  610.                         case 'ZOO ':
  611.  
  612.                             Type = TYPE_ZOO;
  613.                             break;
  614.  
  615.                         case 'GIF8':
  616.  
  617.                             Type = TYPE_GIF;
  618.                             break;
  619.                     }
  620.                 }
  621.  
  622.                     /* Now for oddly placed magic cookies... */
  623.  
  624.                 if(Type == TYPE_FILE)
  625.                 {
  626.                         /* Dumb check for PCX (awful header -- just
  627.                          * a single byte indicates that the file
  628.                          * is supposed to be a PCX file! Those
  629.                          * PC guys just don't have any
  630.                          * decent software culture!).
  631.                          */
  632.  
  633.                     if(CharBuffer[0] == 0x0A)
  634.                         Type = TYPE_PCX;
  635.  
  636.                         /* Yet another awful file format... */
  637.  
  638.                     if(CharBuffer[0] == 'B' && CharBuffer[1] == 'M')
  639.                         Type = TYPE_BMP;
  640.  
  641.                         /* Check for JFIF... */
  642.  
  643.                     if(LongCompare(&CharBuffer[6],'JFIF'))
  644.                         Type = TYPE_JFIF;
  645.  
  646.                         /* Check for `freeze' output file. */
  647.  
  648.                     if(CharBuffer[0] == (UBYTE)'\037' && CharBuffer[1] >= (UBYTE)'\236')
  649.                         Type = TYPE_FREEZE;
  650.                 }
  651.  
  652.                     /* Check for Macintosh data (note:
  653.                      * this code assumes that the Mac
  654.                      * binary header is still present,
  655.                      * so if you are dealing with stripped
  656.                      * binary files, don't expect the
  657.                      * following code to work!).
  658.                      */
  659.  
  660.                 if(Type == TYPE_FILE)
  661.                 {
  662.                     UBYTE *ByteBuffer = &((UBYTE *)Buffer)[65];
  663.  
  664.                         /* Check for MacPaint... */
  665.  
  666.                     if(LongCompare(ByteBuffer,'PNTG'))
  667.                         Type = TYPE_MACPAINT;
  668.  
  669.                         /* Check for SuperPaint... */
  670.  
  671.                     if(LongCompare(ByteBuffer,'SPTG'))
  672.                         Type = TYPE_SUPERPAINT;
  673.  
  674.                         /* Check for PICT... */
  675.  
  676.                     if(LongCompare(ByteBuffer,'PICT'))
  677.                         Type = TYPE_PICT;
  678.  
  679.                         /* Check for executable... */
  680.  
  681.                     if(LongCompare(ByteBuffer,'APPL') || LongCompare(ByteBuffer,'PRES') || LongCompare(ByteBuffer,'FDOC') || LongCompare(ByteBuffer,'cdev') || LongCompare(ByteBuffer,'INIT'))
  682.                         Type = TYPE_MACEXECUTABLE;
  683.  
  684.                         /* Check for StuffIt archive... */
  685.  
  686.                     if(LongCompare(ByteBuffer,'SIT!') || LongCompare(ByteBuffer,'SIT2'))
  687.                         Type = TYPE_STUFFIT;
  688.  
  689.                         /* Check for PackIt archive... */
  690.  
  691.                     if(LongCompare(ByteBuffer,'PIT '))
  692.                         Type = TYPE_PACKIT;
  693.  
  694.                         /* Check for self-extracting Compact archive. */
  695.  
  696.                     if(LongCompare(ByteBuffer,'APPL') && LongCompare(&ByteBuffer[4],'EXTR'))
  697.                         Type = TYPE_COMPACT;
  698.  
  699.                         /* Check for MacCompress archive. */
  700.  
  701.                     if(LongCompare(ByteBuffer,'ZIVM'))
  702.                         Type = TYPE_MACCOMPRESS;
  703.  
  704.                         /* Check for LhArc archive with MacBinary header. */
  705.  
  706.                     if(LongCompare(ByteBuffer,'LARC'))
  707.                         Type = TYPE_LHARC;
  708.  
  709.                         /* Check for Compact archive. */
  710.  
  711.                     if(LongCompare(ByteBuffer,'PACT'))
  712.                         Type = TYPE_COMPACT;
  713.  
  714.                         /* Check for Diamond archive. */
  715.  
  716.                     if(LongCompare(ByteBuffer,'Pack'))
  717.                         Type = TYPE_DIAMOND;
  718.                 }
  719.  
  720.                     /* Still no match? Have another try... */
  721.  
  722.                 if(Type == TYPE_FILE)
  723.                 {
  724.                     if((Buffer[0] & 0x0000FFFF) == 0x00002D6C && (Buffer[1] & 0xFF00FF00) == 0x68002D00)
  725.                     {
  726.                         if(CharBuffer[5] == '5')
  727.                             Type = TYPE_LHA;
  728.                         else
  729.                             Type = TYPE_LHARC;
  730.                     }
  731.                     else
  732.                     {
  733.                         switch(Buffer[0] & 0xFFFF0000)
  734.                         {
  735.                             case 0x4D4D0000:
  736.                             case 0x49490000:
  737.  
  738.                                 Type = TYPE_TIFF;
  739.                                 break;
  740.  
  741.                             case 0x1A080000:
  742.  
  743.                                 Type = TYPE_ARC;
  744.                                 break;
  745.  
  746.                             case 0x60EA0000:
  747.  
  748.                                 Type = TYPE_ARJ;
  749.                                 break;
  750.  
  751.                             case 0x434A0000:
  752.  
  753.                                 Type = TYPE_NEWMANX;
  754.                                 break;
  755.  
  756.                             case 0x414A0000:
  757.  
  758.                                 Type = TYPE_OLDMANX;
  759.                                 break;
  760.  
  761.                             case 0x636A0000:
  762.  
  763.                                 Type = TYPE_NEWMANXLIB;
  764.                                 break;
  765.  
  766.                             case 0x616A0000:
  767.  
  768.                                 Type = TYPE_OLDMANXLIB;
  769.                                 break;
  770.  
  771.                             case 0xF5000000:
  772.  
  773.                                 Type = TYPE_BASIC;
  774.                                 break;
  775.  
  776.                             case 0xE3100000:
  777.  
  778.                                 Type = TYPE_ICON;
  779.                                 break;
  780.  
  781.                             case 0x4D5A0000:
  782.  
  783.                                 Type = TYPE_MSDOSEXECUTABLE;
  784.                                 break;
  785.  
  786.                             case 0x601A0000:
  787.  
  788.                                 Type = TYPE_ATARIEXECUTABLE;
  789.                                 break;
  790.  
  791.                             case 0x80000000:
  792.  
  793.                                 Type = TYPE_DEGAS;
  794.                                 break;
  795.                         }
  796.                     }
  797.                 }
  798.  
  799.                     /* Take a look at the file name
  800.                      * suffixes.
  801.                      */
  802.  
  803.                 switch(Type)
  804.                 {
  805.                     case TYPE_TEXT:
  806.  
  807.                         for(i = 0 ; i < sizeof(TextSuffix) / sizeof(struct Suffix) ; i++)
  808.                         {
  809.                             Size = strlen(TextSuffix[i] . Name);
  810.  
  811.                             if(Len >= Size)
  812.                             {
  813.                                 if(!Stricmp(&Name[Len - Size],TextSuffix[i] . Name))
  814.                                 {
  815.                                     Type = TextSuffix[i] . Type;
  816.                                     break;
  817.                                 }
  818.                             }
  819.                         }
  820.  
  821.                             /* Is it still a text file? */
  822.  
  823.                         if(Type == TYPE_TEXT)
  824.                         {
  825.                                 /* Check for magic cookies. */
  826.  
  827.                             for(i = 0 ; i < sizeof(MagicCookies) / sizeof(STRPTR) ; i++)
  828.                             {
  829.                                 if(!memcmp(CharBuffer,MagicCookies[i],strlen(MagicCookies[i])))
  830.                                 {
  831.                                     TypeName = LocaleString(MSG_IDENTIFY_COOKIE_0 + i);
  832.  
  833.                                     break;
  834.                                 }
  835.                             }
  836.                         }
  837.  
  838.                         break;
  839.  
  840.                     case TYPE_EXECUTABLE:
  841.  
  842.                         for(i = 0 ; i < sizeof(ExecutableSuffix) / sizeof(struct Suffix) ; i++)
  843.                         {
  844.                             Size = strlen(ExecutableSuffix[i] . Name);
  845.  
  846.                             if(Len >= Size)
  847.                             {
  848.                                 if(!Stricmp(&Name[Len - Size],ExecutableSuffix[i] . Name))
  849.                                 {
  850.                                     Type = ExecutableSuffix[i] . Type;
  851.                                     break;
  852.                                 }
  853.                             }
  854.                         }
  855.  
  856.                         break;
  857.  
  858.                     case TYPE_OBJECT:
  859.  
  860.                         if(Len >= 4)
  861.                         {
  862.                             if(!Stricmp(&Name[Len - 4],".LIB"))
  863.                                 Type = TYPE_LIB;
  864.                         }
  865.  
  866.                         break;
  867.                 }
  868.             }
  869.  
  870.             Close(File);
  871.         }
  872.  
  873.         FreeVecPooled(Buffer);
  874.     }
  875.  
  876.     if(AttachComment)
  877.     {
  878.         if(Type > TYPE_FILE || TypeName)
  879.         {
  880.             if(Type == TYPE_IFF)
  881.             {
  882.                 UBYTE NameBuffer[40];
  883.  
  884.                 SPrintf(NameBuffer,LocaleString(MSG_IDENTIFY_IFF_FILE),IFFType);
  885.  
  886.                 SetComment(Name,NameBuffer);
  887.             }
  888.             else
  889.             {
  890.                 if(TypeName)
  891.                     SetComment(Name,TypeName);
  892.                 else
  893.                     SetComment(Name,LocaleString(TypeID[Type - TYPE_ICON]));
  894.             }
  895.         }
  896.  
  897.             /* Is it an executable file? */
  898.  
  899.         if(Type != TYPE_EXECUTABLE && Type != TYPE_LHPAK && Type != TYPE_LHASFX)
  900.         {
  901.             BPTR FileLock;
  902.  
  903.                 /* Get a lock on it. */
  904.  
  905.             if(FileLock = Lock(Name,ACCESS_WRITE))
  906.             {
  907.                 struct FileInfoBlock *FileInfo;
  908.  
  909.                     /* Allocate fileinfo data. */
  910.  
  911.                 if(FileInfo = (struct FileInfoBlock *)AllocDosObjectTags(DOS_FIB,TAG_DONE))
  912.                 {
  913.                         /* Take a closer look at it... */
  914.  
  915.                     if(Examine(FileLock,FileInfo))
  916.                     {
  917.                             /* Release the lock. */
  918.  
  919.                         UnLock(FileLock);
  920.  
  921.                             /* Really drop it. */
  922.  
  923.                         FileLock = NULL;
  924.  
  925.                             /* Update protection bits. */
  926.  
  927.                         SetProtection(Name,FileInfo -> fib_Protection | FIBF_EXECUTE);
  928.                     }
  929.  
  930.                         /* Free fileinfo data. */
  931.  
  932.                     FreeDosObject(DOS_FIB,FileInfo);
  933.                 }
  934.             }
  935.  
  936.                 /* Release the lock if still allocated. */
  937.  
  938.             if(FileLock)
  939.                 UnLock(FileLock);
  940.         }
  941.     }
  942.  
  943.     return(Type);
  944. }
  945.  
  946.     /* Identify(STRPTR Name):
  947.      *
  948.      *    Try to identify the type of a file,
  949.      *    attach an icon if necessary.
  950.      */
  951.  
  952. VOID
  953. Identify(STRPTR Name,BOOL AttachComment)
  954. {
  955.     LONG Type = GetFileType(Name,AttachComment);
  956.  
  957.     if(Config -> MiscConfig -> CreateIcons)
  958.         AddIcon(Name,FileTypes[Type],FALSE);
  959. }
  960.  
  961.     /* AddIcon(STRPTR Name,LONG Type,BOOL Override):
  962.      *
  963.      *    Add an icon to a file.
  964.      */
  965.  
  966. VOID
  967. AddIcon(STRPTR Name,LONG Index,BOOL Override)
  968. {
  969.     if(ClassIconNames[Index] && IconBase)
  970.     {
  971.         struct DiskObject *Icon;
  972.  
  973.         if(!Override)
  974.         {
  975.             if(Icon = GetDiskObject(Name))
  976.             {
  977.                 FreeDiskObject(Icon);
  978.  
  979.                 return;
  980.             }
  981.         }
  982.  
  983.         if(!(Icon = GetDiskObject(ClassIconNames[Index])))
  984.         {
  985.             if(Index == FILETYPE_PROGRAM)
  986.                 Icon = GetDefDiskObject(WBTOOL);
  987.             else
  988.             {
  989.                 AddProtection(Name,FIBF_EXECUTE);
  990.  
  991.                 Icon = GetDiskObjectNew(Name);
  992.             }
  993.         }
  994.  
  995.         if(Icon)
  996.         {
  997.             Icon -> do_CurrentX = Icon -> do_CurrentY = NO_ICON_POSITION;
  998.  
  999.             PutDiskObject(Name,Icon);
  1000.  
  1001.             FreeDiskObject(Icon);
  1002.         }
  1003.     }
  1004. }
  1005.